/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package assignmentbuilder;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

/**
 *
 * @author keith
 */
public class XMLContentFile extends ContentFile {

  public XMLContentFile(String name) {
    super(name);
  }

  protected String getTopics() {
    return "loops, accumulation, average, mean, random numbers";
  }

  protected String getPrerequisites() {
    return "main programs, variables, assignment statements";
  }

  protected String getCourseList() {
    return "CS1, CSC1051: Algorithms & Data Structures I";
  }

  protected String getProgrammingLanguage() {
    return "Java";
  }

  protected String getTitle() {
    return "Dice Rolling Experiment";
  }

  protected static Author defaultAuthor = new Author("Jane", "Hacker",
          "j.hacker@acm.org", "+1 234 547-8901",
          "Villanova University, Dept. of Computing Science", "http://...");

  protected List<Author> getAuthors() {
    final List<Author> authors = new ArrayList<Author>();
    final Author a = defaultAuthor;

    authors.add(a);
    return authors;
  }

  final private byte[] createDom() throws SAXException, MalformedURLException,
          ParserConfigurationException,
          TransformerConfigurationException,
          TransformerException, IOException {
    final DateFormat dtFmt = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss z");

    final String nsUri = "http://web-cat.org/1.0/assignment-sharing";

    final SchemaFactory schFac = SchemaFactory.newInstance(
            XMLConstants.W3C_XML_SCHEMA_NS_URI);
//    Schema assignmentSchema = schFac.newSchema( new URL(
//      "http://amethyst.ipfw.edu:8080/cs590-project/assignment-sharing.xsd" ) );
    final File schemaFile =
            new File(
            "../CheatApp/CheatApp-common/xml-resources/jaxb/Assignment Sharing/amethyst.ipfw.edu_8080/cs590-project/assignment-sharing.xsd");
    Schema assignmentSchema = schFac.newSchema(schemaFile);

    final DocumentBuilderFactory docBldFac = DocumentBuilderFactory.newInstance();
    docBldFac.setSchema(assignmentSchema);
    docBldFac.setNamespaceAware(true);
    docBldFac.setCoalescing(true);

    final DocumentBuilder docBld = docBldFac.newDocumentBuilder();
    final Document assignment = docBld.newDocument();

    assignment.setXmlVersion("1.1");
    assignment.setDocumentURI(nsUri);
    assignment.setXmlStandalone(true);

    final Element root = assignment.createElementNS(nsUri, "assignment");

    assignment.appendChild(root);
    root.setAttribute("xmlns", nsUri);

    final Element title = assignment.createElementNS(nsUri, "title");
    title.appendChild(assignment.createTextNode(getTitle()));
    root.appendChild(title);

    final Element abstrct = assignment.createElementNS(nsUri, "abstract");
    abstrct.appendChild(assignment.createTextNode(
            "Build a class that simulates rolling two pair of dice, one "));
    abstrct.appendChild(assignment.createTextNode(
            "containing two 6-sided dice, and the other containing a "));
    abstrct.appendChild(assignment.createTextNode(
            "two-sided die and a 10-sided die. The program will read in "));
    abstrct.appendChild(assignment.createTextNode(
            "the number of rolls to make, roll each pair the requested "));
    abstrct.appendChild(assignment.createTextNode(
            "number of times, and then present the average sum of each "));
    abstrct.appendChild(assignment.createTextNode(
            "roll for both pairs. This allows you to carry out a lab "));
    abstrct.appendChild(assignment.createTextNode(
            "experiment to experimentally test whether one of these pairs "));
    abstrct.appendChild(assignment.createTextNode(
            "of dice tends to give a larger combined value, on average."));
    root.appendChild(abstrct);

    final Element programLang =
            assignment.createElementNS(nsUri, "programming-language");
    programLang.setAttribute("name", getProgrammingLanguage());
    root.appendChild(programLang);

    for (Author a : getAuthors()) {
      final Element author = assignment.createElementNS(nsUri, "author");
      root.appendChild(author);

      final Element first = assignment.createElementNS(nsUri, "first-name");
      first.appendChild(assignment.createTextNode(a.getFirstName()));
      author.appendChild(first);

      final Element last = assignment.createElementNS(nsUri, "last-name");
      last.appendChild(assignment.createTextNode(a.getLastName()));
      author.appendChild(last);

      final Element email = assignment.createElementNS(nsUri, "email");
      email.appendChild(assignment.createTextNode(a.getEmail()));
      author.appendChild(email);

      final Element url = assignment.createElementNS(nsUri, "url");
      url.appendChild(assignment.createTextNode(a.getUrl()));
      author.appendChild(url);

      final Element affiliation = assignment.createElementNS(nsUri, "affiliation");
      affiliation.appendChild(assignment.createTextNode(a.getAffiliation()));
      author.appendChild(affiliation);

      final Element phone = assignment.createElementNS(nsUri, "phone");
      phone.appendChild(assignment.createTextNode(a.getPhone()));
      author.appendChild(phone);
    }

    final Element date = assignment.createElementNS(nsUri, "date");
    final Calendar now = Calendar.getInstance();
    dtFmt.setTimeZone(TimeZone.getTimeZone("UTC"));

    date.setAttribute("created", dtFmt.format(now.getTime()));
    date.setAttribute("modified", dtFmt.format(now.getTime()));
    root.appendChild(date);

    final Element languages = assignment.createElementNS(nsUri, "languages");
    languages.appendChild(assignment.createTextNode("eng"));
    root.appendChild(languages);

    final Element rights = assignment.createElementNS(nsUri, "rights");
    root.appendChild(rights);

    final Element copyright = assignment.createElementNS(nsUri, "copyright");
    copyright.appendChild(assignment.createTextNode("(c) 2008 Villanova University"));
    rights.appendChild(copyright);

    final Element license = assignment.createElementNS(nsUri, "license");
    license.appendChild(assignment.createTextNode(
            "Creative Commons Attribution-Noncommercial 3.0 United States License"));
    rights.appendChild(license);

    Element url = assignment.createElementNS(nsUri, "url");
    url.appendChild(assignment.createTextNode(
            "http://creativecommons.org/licenses/by-nc/3.0/us/"));
    rights.appendChild(url);

    final Element keywords = assignment.createElementNS(nsUri, "keywords");
    root.appendChild(keywords);

    final Element topics = assignment.createElementNS(nsUri, "topics");
    topics.appendChild(assignment.createTextNode(getTopics()));
    keywords.appendChild(topics);

    final Element prerequisites = assignment.createElementNS(nsUri, "prerequisites");
    prerequisites.appendChild(assignment.createTextNode(getPrerequisites()));
    keywords.appendChild(prerequisites);

    final Element other = assignment.createElementNS(nsUri, "other");
    other.appendChild(assignment.createTextNode("experiment, lab"));
    keywords.appendChild(other);

    final Element course = assignment.createElementNS(nsUri, "course");
    course.appendChild(assignment.createTextNode(getCourseList()));
    keywords.appendChild(course);

    final Element type = assignment.createElementNS(nsUri, "type");
    type.appendChild(assignment.createTextNode("program"));
    root.appendChild(type);

    final Element command = assignment.createElementNS(nsUri, "command");
    root.appendChild(command);

    final Element build = assignment.createElementNS(nsUri, "build");
    build.appendChild(assignment.createTextNode("javac *.java"));
    command.appendChild(build);

    final Element test = assignment.createElementNS(nsUri, "test");
    test.appendChild(assignment.createTextNode("for file in in*.txt\n" +
            "do\n" +
            "  java DiceExperiment < $file > $file.out\n" +
            "done"));
    command.appendChild(test);

    final Element learningObj = assignment.createElementNS(nsUri, "learning-objectives");
    learningObj.appendChild(
            assignment.createTextNode(
            "This assignment is designed to allow students to practice writing basic looping structures ..."));
    root.appendChild(learningObj);

    final Element prereq = assignment.createElementNS(nsUri, "prerequisite-assignments");
    prereq.appendChild(assignment.createTextNode("18"));
    root.appendChild(prereq);

    final Element info = assignment.createElementNS(nsUri, "info");
    root.appendChild(info);

    final Element info_url = assignment.createElementNS(nsUri, "url");
    info_url.appendChild(assignment.createTextNode(
            "http://csc.villanova.edu/~csc1051/assignments/dice.html"));
    info.appendChild(info_url);

    final Element info_cite = assignment.createElementNS(nsUri, "cite");
    info_cite.appendChild(assignment.createTextNode(
            "http://doi.acm.org/10.1145/1384271.1384303"));
    info.appendChild(info_cite);

    final Element estimated = assignment.createElementNS(nsUri, "estimated");
    estimated.setAttribute("difficulty", "3");
    estimated.setAttribute("time", "1 week");
    estimated.setAttribute("size", "120");
    root.appendChild(estimated);

    final Element repos = assignment.createElementNS(nsUri, "repository");
    root.appendChild(repos);

    final Element repos_root = assignment.createElementNS(nsUri, "root");
    repos.appendChild(repos_root);

    final Element history = assignment.createElementNS(nsUri, "history");
    history.appendChild(assignment.createTextNode("Initial version"));
    repos.appendChild(history);

    final Element acl = assignment.createElementNS(nsUri, "acl");
    repos.appendChild(acl);

    final Element cust = assignment.createElementNS(nsUri, "custom-properties");
    root.appendChild(cust);

    final Element property = assignment.createElementNS(nsUri, "property");
    property.setAttribute("name", "custom.property");
    property.setAttribute("value", "some value");
    cust.appendChild(property);

//    dom.Writer dump = new dom.Writer();
//    dump.setOutput( new OutputStreamWriter( System.out ) );
////    dump.setCanonical( true );
//    dump.write( assignment );
//
//    System.out.println("\n");

    final TransformerFactory transFac = TransformerFactory.newInstance();
    Transformer trans = transFac.newTransformer();

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    trans.transform(new DOMSource(assignment), new StreamResult(baos));

    // check that the created doc is valid
    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    Document validDoc = docBld.parse(bais);

    return baos.toByteArray();
  }

  @Override
  public byte[] getByes() {
    byte[] contents = new byte[]{};

    try {
      contents = createDom();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    return contents;
  }

  static public void main(String[] argv) throws SAXException, MalformedURLException,
          ParserConfigurationException,
          TransformerConfigurationException,
          TransformerException, IOException {
    new XMLContentFile("assignment.xml").createDom();
  }
}
